package com.metadata_system.system.service;

import com.alibaba.fastjson.JSON;
import com.metadata_system.common.db.entity.*;
import com.metadata_system.common.db.mapper.*;
import com.metadata_system.common.dto.ApiResult;
import com.metadata_system.common.dto.MetadataAllItem;
import com.metadata_system.common.enums.AllConst;
import com.metadata_system.common.service.UserOperationLogService;
import com.metadata_system.system.request.MetadataListParams;
import com.metadata_system.system.response.MetadataDetailResponse;
import com.metadata_system.system.response.NodeItem;
import com.metadata_system.system.response.NodePropertiesItem;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MetadataService {
    @Autowired(required = false)
    private MetadataMapper metadataMapper;
    @Autowired(required = false)
    private MetadataNodeMapper metadataNodeMapper;
    @Autowired(required = false)
    private MetadataViewMapper metadataViewMapper;
    @Autowired(required = false)
    private MetadataEdgeMapper metadataEdgeMapper;

    /**
     * 获取-元数据列表
     *
     * @param listParams
     * @return
     */
    public ApiResult getList(MetadataListParams listParams) {
        Example example = new Example(Metadata.class);
        Example.Criteria criteria = example.createCriteria();
        if (!StringUtils.isBlank(listParams.getName())) {
            criteria.andLike("name", "%" + listParams.getName() + "%");
        }
        listParams.setOrder(example, "id,updatedTime");
        if (!StringUtils.isBlank(listParams.getCreatedTime())) {
            listParams.setConditionTime(listParams.getCreatedTime(), criteria, "createdTime");
        }
        int total = this.metadataMapper.selectCountByExample(example);
        List<Metadata> list = new ArrayList<>();
        if (total > 0) {
            list = this.metadataMapper.selectByExampleAndRowBounds(example, listParams.getRowRunds());
        }
        return ApiResult.successPage(list, total);
    }

    /**
     * 获取元数据详情
     *
     * @param id
     * @return
     */
    public ApiResult getDetail(Integer id) {
        Metadata metadata = this.metadataMapper.selectByPrimaryKey(id);
        if (metadata == null) {
            return ApiResult.error("元数据不存在");
        }


        Example exampleEdge = new Example(MetadataEdge.class);
        exampleEdge.createCriteria().andEqualTo("metadataId", id);
        List<MetadataEdge> listEdge = this.metadataEdgeMapper.selectByExample(exampleEdge);

        Example exampleNode = new Example(MetadataNode.class);
        exampleNode.createCriteria().andEqualTo("metadataId", id);
        List<MetadataNode> listNode = this.metadataNodeMapper.selectByExample(exampleNode);


        MetadataDetailResponse response = MetadataDetailResponse.fromEntity(metadata, listNode, listEdge, metadata.getDefaultViewId());

        return ApiResult.success(response);
    }


    /**
     * 获取元数据详情
     *
     * @param id
     * @return
     */
    public ApiResult getDetailByVewId(Integer id) {
        return this.getDetail(this.metadataViewMapper.getMetadataIdByViewId(id));
    }


    /**
     * 新增-元数据
     *
     * @param metadata
     * @return
     */
    public ApiResult create(Metadata metadata, Integer userId) {
        // 校验参数
        if (StringUtils.isBlank(metadata.getName())) {
            return ApiResult.error("名称不能为空");
        }
        if (metadata.getName().length() < 2 || metadata.getName().length() > 30) {
            return ApiResult.error("名称长度必须在2-30个字符之间");
        }
        // 校验名称是否重复
        Example example = new Example(Metadata.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("name", metadata.getName());
        int i = this.metadataMapper.selectCountByExample(example);
        if (i > 0) {
            return ApiResult.error("名称重复");
        }

        metadata.setEnableEdgeArr(AllConst.EnableEdgeArrString);
        metadata.setCreatedTime(new Date());
        metadata.setUpdatedTime(new Date());
        this.metadataMapper.insertSelective(metadata);
        Integer metadataId = this.metadataMapper.getLastInsertId();
        this.metadataViewService.create(MetadataView.builder()
                .metadataId(metadataId)
                .name("默认视图")
                .shortName("默认")
                .build(), userId);
        Integer lastInsetId = this.metadataViewMapper.getLastInsertId();
        this.metadataMapper.updateByPrimaryKeySelective(Metadata.builder().id(metadataId).defaultViewId(lastInsetId).build());

        this.updateView(metadataId, userId);

        // 4.操作日志-新增
        userOperationLogService.insert(UserOperationLog.builder()
                .userId(metadata.getCreatedUserId())
                .username(this.userMapper.selectByPrimaryKey(userId).getUsername())
                .type("Metadata.Create")
                .content("新增元模型: " + metadata.getName())
                .params(lastInsetId.toString())
                .createdTime(new Date())
                .build());
        return ApiResult.success();
    }

    @Autowired
    MetadataViewService metadataViewService;
    @Autowired
    UserOperationLogService userOperationLogService;
    @Autowired(required = false)
    UserMapper userMapper;

    /**
     * 更新-元数据视图
     *
     * @param id
     */
    public void updateView(Integer id, Integer userId) {
        Metadata metadata = this.metadataMapper.selectByPrimaryKey(id);
        if (metadata == null) {
            return;
        }

        // 如果默认视图不存在，就设置为第一个视图
        if (this.metadataViewMapper.selectByPrimaryKey(metadata.getDefaultViewId()) == null) {
            Integer newDefaultViewId = this.metadataViewMapper.getViewIdByMetadataId(id);
            if (newDefaultViewId != null) {
                this.metadataMapper.updateByPrimaryKeySelective(Metadata.builder().id(metadata.getId()).defaultViewId(newDefaultViewId).build());
                this.userOperationLogService.insert(UserOperationLog.builder()
                        .userId(userId)
                        .username(this.userMapper.selectByPrimaryKey(userId).getUsername())
                        .content("更改-元数据视图,联动更新: " + metadata.getName())
                        .type("Metadata.Update")
                        .params(id.toString())
                        .createdTime(new Date())
                        .build());
            }
        }


        this.metadataMapper.updateMetadataStats(id);
    }


    /**
     * 更新-元数据
     *
     * @param metadataParams
     * @return
     */
    public ApiResult update(Metadata metadataParams, Integer systemUserId) {
        Metadata metadata = this.metadataMapper.selectByPrimaryKey(metadataParams.getId());
        if (metadata == null) {
            return ApiResult.error("元数据不存在");
        }
        Metadata updateMetadata = Metadata.builder().id(metadata.getId()).build();
        // 校验参数
        if (metadataParams.getName() != null) {
            if (StringUtils.isBlank(metadataParams.getName())) {
                return ApiResult.error("名称不能为空");
            }
            if (metadataParams.getName().length() < 2 || metadataParams.getName().length() > 30) {
                return ApiResult.error("名称长度必须在2-30个字符之间");
            }
            updateMetadata.setName(metadataParams.getName());
            // 校验名称是否重复
            Example example = new Example(Metadata.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("name", metadataParams.getName());
            criteria.andNotEqualTo("id", metadataParams.getId());
            int i = this.metadataMapper.selectCountByExample(example);
            if (i > 0) {
                return ApiResult.error("名称重复");
            }
        }
        if (metadataParams.getShortName() != null) {
            if (StringUtils.isBlank(metadataParams.getShortName())) {
                return ApiResult.error("简称不能为空");
            }
            if (metadataParams.getShortName().isEmpty() || metadataParams.getShortName().length() > 3) {
                return ApiResult.error("简称长度必须在1-3个字符之间");
            }
            updateMetadata.setShortName(metadataParams.getShortName());
        }
        if (metadataParams.getEnableEdgeArr() != null) {
            updateMetadata.setEnableEdgeArr(metadataParams.getEnableEdgeArr());
        }


        this.metadataMapper.updateByPrimaryKeySelective(metadataParams);

        // 3.新增操作日志
        userOperationLogService.insert(UserOperationLog.builder()
                .userId(systemUserId)
                .username(this.userMapper.selectByPrimaryKey(systemUserId).getUsername())
                .type("Metadata.Update")
                .content("更新元模型: " + updateMetadata.getName())
                .params(updateMetadata.getId().toString())
                .createdTime(new Date())
                .build());
        return ApiResult.success();
    }


    /**
     * 删除元数据
     *
     * @param id
     * @return
     */
    public ApiResult delete(Integer id, Integer systemUserId) {
        Metadata metadata = this.metadataMapper.selectByPrimaryKey(id);
        if (metadata == null) {
            return ApiResult.error("元数据不存在");
        }


        // 操作日志-新增
        addDeleteLog(metadata, systemUserId);


        this.metadataMapper.deleteByPrimaryKey(id);
        this.metadataNodeMapper.deleteByMetadataId(id);
        this.metadataEdgeMapper.deleteByMetadataId(id);
        this.metadataViewMapper.deleteByMetadataId(id);
        return ApiResult.success();
    }


    public void addDeleteLog(Metadata metadata, Integer systemUserId) {

        String username = this.userMapper.selectByPrimaryKey(systemUserId).getUsername();

        List<Integer> nodeIds = this.metadataNodeMapper.getIdsByMetadataId(metadata.getId());
        List<Integer> edgeIds = this.metadataEdgeMapper.getIdsByMetadataId(metadata.getId());
        List<Integer> viewIds = this.metadataViewMapper.getIdsByMetadataId(metadata.getId());

        if (!nodeIds.isEmpty()) {
            this.userOperationLogService.insert(UserOperationLog.builder()
                    .userId(systemUserId)
                    .username(username)
                    .type("MetadataNode.Delete")
                    .content("删除元模型,联动删除元数据-节点: " + nodeIds.size() + "个")
                    .params(String.join(",", nodeIds.stream().map(String::valueOf).collect(Collectors.toList())))
                    .createdTime(new Date())
                    .build());
        }

        if (!edgeIds.isEmpty()) {
            this.userOperationLogService.insert(UserOperationLog.builder()
                    .userId(systemUserId)
                    .username(username)
                    .type("MetadataEdge.Delete")
                    .content("删除元模型,联动删除元数据-关系: " + edgeIds.size() + "个")
                    .params(String.join(",", edgeIds.stream().map(String::valueOf).collect(Collectors.toList())))
                    .createdTime(new Date())
                    .build());
        }

        if (!viewIds.isEmpty()) {
            this.userOperationLogService.insert(UserOperationLog.builder()
                    .userId(systemUserId)
                    .username(username)
                    .type("MetadataView.Delete")
                    .content("删除元模型,联动删除元数据-视图: " + viewIds.size() + "个")
                    .params(String.join(",", viewIds.stream().map(String::valueOf).collect(Collectors.toList())))
                    .createdTime(new Date())
                    .build());
        }

        userOperationLogService.insert(UserOperationLog.builder()
                .userId(systemUserId)
                .username(username)
                .type("Metadata.Delete")
                .content("删除元数据: " + metadata.getName())
                .params(metadata.toString())
                .createdTime(new Date())
                .build());
    }


    /**
     * 获取所有元数据+视图+节点
     *
     * @return
     */
    public ApiResult getAllList() {
        List<Metadata> list = this.metadataMapper.selectAll();
        List<MetadataView> listView = this.metadataViewMapper.selectAll();
        List<MetadataNode> metadataNodes = this.metadataNodeMapper.selectDistinctByUniqueKey();

        List<MetadataAllItem> listAll = new ArrayList<>();
        for (Metadata metadata : list) {
            MetadataAllItem metadataAllItem = MetadataAllItem.builder()
                    .id(metadata.getId())
                    .value(metadata.getId())
                    .label(metadata.getName())
                    .properties(new ArrayList<>())
                    .build();
            metadataAllItem.setChildren(new ArrayList<>());
            for (MetadataView metadataView : listView) {
                if (metadataView.getMetadataId().equals(metadata.getId())) {
                    MetadataAllItem currView = MetadataAllItem.builder()
                            .id(metadataView.getId())
                            .value(metadataView.getId())
                            .label(metadataView.getName())
                            .properties(new ArrayList<>())
                            .build();

                    currView.setChildren(new ArrayList<>());
                    for (MetadataNode metadataNode : metadataNodes) {
                        if (metadataNode.getMetadataId().equals(metadata.getId())) {
                            currView.getChildren().add(MetadataAllItem.builder()
                                    .id(metadataNode.getId())
                                    .value(metadataNode.getId())
                                    .label(metadataNode.getName())
                                    .properties(JSON.parseArray(metadataNode.getProperties(), NodePropertiesItem.class))
                                    .build());
                        }
                    }

                    if (!currView.getChildren().isEmpty()) {
                        metadataAllItem.getChildren().add(currView);
                    }

                }
            }

            if (!metadataAllItem.getChildren().isEmpty()) {
                listAll.add(metadataAllItem);
            }
        }


        return ApiResult.success(listAll);
    }


    public ApiResult getNodeList(Integer id) {
        List<MetadataNode> list = this.metadataNodeMapper.selectDistinctByUniqueKeyByMetadataId(id);
        return ApiResult.success(NodeItem.fromEntity(list));
    }


    public void updateDataTotal(Integer metadataId, Integer userId) {
        Integer dataTotal = this.metadataNodeMapper.getDataTotalByMetadataId(metadataId);
        this.metadataMapper.updateByPrimaryKeySelective(Metadata.builder()
                .id(metadataId)
                .dataTotal(dataTotal)
                .build());
        this.userOperationLogService.insert(UserOperationLog.builder()
                .userId(userId)
                .username(this.userMapper.selectByPrimaryKey(userId).getUsername())
                .type("Metadata.Update")
                .content("更新元数据: " + this.metadataMapper.selectByPrimaryKey(metadataId).getName() + " 数据总条数: " + dataTotal)
                .params(metadataId + "|" + dataTotal)
                .createdTime(new Date())
                .build());
    }
}
